package com.yn.courseselectionsystem.controller;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.yn.courseselectionsystem.pojo.Appointment;
import com.yn.courseselectionsystem.pojo.Course;
import com.yn.courseselectionsystem.pojo.CourseRecord;
import com.yn.courseselectionsystem.pojo.User;
import com.yn.courseselectionsystem.server.SocketServer;
import com.yn.courseselectionsystem.service.impl.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.jms.Queue;
import javax.servlet.http.HttpSession;
import java.util.*;

/**
 * @description: TODO
 * @author: Tokyo_God
 * @date: 2021/1/3 10:59
 * Role of:
 * @version: v1.0
 */
//@SessionAttributes(value = {"user"})加上这个还能访问到那边会话的user的,
// 应该说整个程序 只有这一个@SessionAttributes
@SessionAttributes(value = {"user","hintMsg"})//hintMsg:有人退课后会通知
@Controller
public class CourseController {
    @Autowired
    private Queue queue;
    //消息中间件的搞发送消息的
    @Autowired
    private JmsMessagingTemplate jms;

    @Resource
    CourseServiceImpl courseService;
    @Autowired
    SemesterServiceImpl semesterService;
    @Resource
    TeacherServiceImpl teacherService;
    @Resource
    CourseRecordServiceImpl courseRecordService;
    @Resource
    private SocketServer socketServer;//站内信

    @Resource
    private AppointmentServiceImpl appointmentService;

    @Resource
    RedisTemplate template;//别用自己的RedisTemplate<String, Object>除非你你要在自己这一个项目中搞
                        //自己配置的会自动把对象转成json字符串，拿出来他也会自动转换成Object对象
                        //所以他在另一个项目中拿出来的时候会出现你那玩意  转换不了这个项目的 类
                        //就说另一个项目不存在这个类的类型


    /**
     * 按条件查询课程信息
     * @param course
     * @param elect
     * @param session
     * @return
     */
    @GetMapping("/studentManagement/succPage/course/selCourseList")
    @ResponseBody
    public Map selCourseList(Integer pageNum,Integer pageSize,Course course, Integer elect, HttpSession session){
        User user= (User) session.getAttribute("user");
        Map map=new HashMap();
        map.put("mysemesters",semesterService.selSemesterMapAll());
        map.put("myteachers",teacherService.selTeacherMapAll());
        map.put("myCRs",courseRecordService.selCRMapKeyCourseIdAll());
//        System.out.println(pageNum+"||"+pageSize);
        //对下面的查询进行分页
        PageHelper.startPage(pageNum,pageSize);
        List<Course> mycourses=courseService.selCourse(elect,course,user);
        PageInfo pageInfo=new PageInfo(mycourses);
        map.put("pageInfo",pageInfo);
        /*map.put("mycourses",mycourses);*/
        System.out.println(pageInfo.toString());
        return map;
    }

    
    /**
     * 进入选课详细页面
     * @return
     */
    @GetMapping("/studentManagement/succPage/course/courseDetails/{id}")
    public String courseDetails(@PathVariable Integer id, Model model){
        //查询课程 放到  model里（request）
        model.addAttribute("id",id);
        /*Map map=new HashMap();
        map.put("myteachers",teacherService.selTeacherMapAll());
        map.put("mycourse",courseService.selCourseId(id));
        model.addAttribute("myCourseMap",map);*/
        Integer ifTheSelected=0;//-1退课  0不可选  1可选

        //@SessionAttributes(value = {"user"})加上这个还能访问到那边会话的user的,
        // 应该说整个程序 只有这一个@SessionAttributes
        List<Course> courseList=courseService//可选集合
                .selCourse(1,new Course(),((User)model.getAttribute("user")));
        for (Course course:courseList){
            if(course.getId()==id){
                ifTheSelected=1;
            }
        }
        if(ifTheSelected==0){
            List<Course> courseList2=courseService//退课集合
                    .selCourse(4,new Course(),((User)model.getAttribute("user")));
            for (Course course:courseList2){
                if(course.getId()==id){
                    ifTheSelected=-1;
                }
            }
        }

        //再次判断（考虑redis）
        User user= (User) model.getAttribute("user");
        SetOperations setOperations=template.opsForSet();
        Set<String> set=setOperations.members("courseRecords");
        if(null!=set&&set.size()>0){
            CourseRecord courseRecord=null;
            for (String jsonStr:set){
                courseRecord= JSON.parseObject(jsonStr,CourseRecord.class);
                //如果redis里面有我这个用户  且选了这个课  那么就说明我选了只是还没跟新
                //所以只需把状态改为不可选（已选或不可选）就行
                if(courseRecord.getCourseId()==id&&user.getId()==courseRecord.getUserId()){
                    ifTheSelected=0;
                }
            }
        }

        model.addAttribute("ifTheSelected",ifTheSelected);
        return "/succPage/courseDetails";
    }

    /**
     * 通过id查找课程对象
     * @param id
     * @return
     */
    @GetMapping("/studentManagement/succPage/course/selCourseId")
    @ResponseBody
    public Map selCourseId(@RequestParam Integer id){
        Course c=courseService.selCourseId(id);
    //再次计算（考虑redis）
        SetOperations setOperations=template.opsForSet();
        Set<String> set=setOperations.members("courseRecords");
        int num=0;
        if(set!=null&&set.size()>0){
            CourseRecord courseRecord=null;
            for (String jsonStr:set){
                courseRecord= JSON.parseObject(jsonStr,CourseRecord.class);
                //如果在redis里面我这个课程已经被选了
                if(c.getId()==courseRecord.getCourseId()){
                    num++;
                }
            }
        }
        //获取真实的数量   但是只要你数量足够还是能选(后面选课有做判断)
        c.setAmount(c.getAmount()-num);

        Map map=new HashMap();
        map.put("myteachers",teacherService.selTeacherMapAll());
        map.put("mycourse",c);
        return map;
    }

    /**
     * 通过id查找课程对象（非详情  不加教师）
     * @param id
     * @return
     */
    @GetMapping("/studentManagement/succPage/course/selCourseId2")
    @ResponseBody
    public Course selCourseId2(@RequestParam Integer id){
        Course c=courseService.selCourseId(id);
    //再次计算（考虑redis）
        SetOperations setOperations=template.opsForSet();
        Set<String> set=setOperations.members("courseRecords");
        int num=0;
        if(set!=null&&set.size()>0){
            CourseRecord courseRecord=null;
            for (String jsonStr:set){
                courseRecord= JSON.parseObject(jsonStr,CourseRecord.class);
                //如果在redis里面我这个课程已经被选了
                if(c.getId()==courseRecord.getCourseId()){
                    num++;
                }
            }
        }
        //获取真实的数量   但是只要你数量足够还是能选
        c.setAmount(c.getAmount()-num);
        return c;
    }


    /**
     * 选课  提取出来的
     * @param id
     * @param model
     * @return
     */
    public void myTakeTheCourse(Integer id,Model model,Integer userId){
        Course course=courseService.selCourseId(id);
        Integer uid=0;
        if(userId!=null){
            uid=userId;
        }else{
            User user= (User) model.getAttribute("user");
            uid=user.getId();
        }
        CourseRecord courseRecord=new CourseRecord(uid,course.getId(),course.getSemesterId(),course.getMarks());

        //////////这里应该写的是  添加集合对象  不是字符串  一个  可考虑集合中存json字符串///////////////////
        //Stirng缓存
//        ValueOperations myRedis=template.opsForValue();
//        myRedis.set("courseRecord", JSON.toJSONString(courseRecord));
//        System.out.println("redis添加缓存:"+myRedis.get("courseRecord"));

        SetOperations setOperations=template.opsForSet();
        /*setOperations.add("courseRecords","{\"courseId\":4,\"semesterId\":3,\"userId\":10,\"worth\":40}");*/
        setOperations.add("courseRecords",JSON.toJSONString(courseRecord));

        //发送用户信息给消费者   选课
        jms.convertAndSend(queue,"addCard");
    }


    /**
     * 选课 （写了高并发）  //////////////////////把这个改成json返回int是否选课成功    在这里判断课程数量是否充足如果够则成功/////////////////////
     * @return
     */
    @GetMapping("/studentManagement/succPage/course/takeTheCourse")
    public String takeTheCourse(@RequestParam(name = "id") Integer id,Model model){
        myTakeTheCourse(id, model,null);//null默认是给自己加选课记录
        return "/succPage/win";
    }


    /**
     * 退课     1.修改状态为退课状态2.添加课程数量
     * @param model
     * @param course
     * @return
     */
    @ResponseBody
    @GetMapping("/studentManagement/succPage/course/dropTheCourse")
    public Integer dropTheCourse(Model model,Course course){

        Course c=courseService.selCourseId(course.getId());
        User user= (User) model.getAttribute("user");
        //退课
        int num=courseService.dropTheCourse(course,user);
        if(num>0){//查看退课是否成功
            //有人退课 就发送消息给全部在线的人
            socketServer.sendAll("用户"+user.getName()+"已退课课程为："+c.getName());


            //按我的预约牌号来  选择userId(谁先预约  就先给谁选)  得加选课记录
            String msg="恭喜你预约的课程"+c.getName()+"到账了";
            //获取最前面预约的人  给他进行选课
            Appointment appointment=appointmentService.nextTakeTheCourse(c);
            /*System.out.println(appointment);
            System.out.println("//////////////////"+msg+"||"+appointment.getUserId()+"");*/
            //发送消息
            socketServer.sendMessage(msg,appointment.getUserId()+"");
            //给 预约的人选课  选课
            myTakeTheCourse(c.getId(), model,appointment.getUserId());//选课
            //修改预约记录为   预约以选课
            appointmentService.upAppointmentTTWin(appointment);

        }
        return num;
    }



    /**
     * 测试
     * @return
     */
    @ResponseBody
    @GetMapping("mytest/{id}")
    public Integer mytest(@PathVariable String id){
        socketServer.sendMessage("你哈哈哈哈哈哈哈哈哈",id);
        return 11;
    }
    

    /**
     * 存储信息（有人退课  ，会有预约好的人选课   就会有退课信息和选课信息）
     * @param msg
     * @param model
     * @return
     */
    @GetMapping("/studentManagement/succPage/course/storeMsg")
    @ResponseBody
    public String storeMsg(@RequestParam String msg,Model model){
        if(model.getAttribute("hintMsg")==null){
            model.addAttribute("hintMsg",new ArrayList<String>());
        }
        List<String> msgs= (List<String>) model.getAttribute("hintMsg");
        msgs.add(msg);
        return "存储成功";
    }

    /**
     * 进入信息页面
     * @return
     */
    @GetMapping("/studentManagement/succPage/course/information")
    public String information(){
        return "/succPage/information";
    }

    /**
     * 打印全部的  信息
     * @param model
     * @return
     */
    @ResponseBody
    @GetMapping("/studentManagement/succPage/course/showAllMsg")
    public List<String> showAllMsg(Model model){
        if(model.getAttribute("hintMsg")==null){
            model.addAttribute("hintMsg",new ArrayList<String>());
        }
        List<String> msgs= (List<String>) model.getAttribute("hintMsg");
        return msgs;
    }
}
